package com.ciaojian.client.util;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.BeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.util.List;
import java.util.Map;

/**
 * JSON处理封装<br>
 * 基于jackson封装
 *
 * @author
 */
@Slf4j
public class JacksonUtil {

    private final static ObjectMapper objectMapper = new ObjectMapper();

    static {
        // 在遇到未知属性的时候不抛出异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 允许序列化空的POJO类
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 忽略空值
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 允许没有引号的字段名（非标准）
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        // 允许单引号（非标准）
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
        // 日期处理
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    /**
     * 避免不小心在类的内部调用构造器. 保证该类在任何情况下都不会被实例化.
     */
    private JacksonUtil() {
    }


    /**
     * 转换复杂对象<br>
     * 常用于Response<T>等泛型多级嵌套的json字符串反序列化
     *
     * @param json
     * @param typeReference
     * @return
     */
    public static <T> T readValue(String json, TypeReference<T> typeReference) {
        try {
            return objectMapper.readValue(json, typeReference);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 转换复杂对象<br>
     * 常用于Response<T>等泛型多级嵌套的json字符串反序列化
     *
     * @param in
     * @param typeReference
     * @return
     */
    public static <T> T readValue(InputStream in, TypeReference<T> typeReference) {
        try {
            return objectMapper.readValue(in, typeReference);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 转换复杂对象<br>
     * 常用于Response<T>等泛型多级嵌套的json字符串反序列化
     *
     * @param bytes
     * @param typeReference
     * @return
     */
    public static <T> T readValue(byte[] bytes, TypeReference<T> typeReference) {
        try {
            return objectMapper.readValue(bytes, typeReference);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }


    /**
     * json转对象
     *
     * @param json
     * @param clazz
     * @return
     */
    public static <T> T parse(String json, Class<T> clazz) {
        if (json == null || json.length() == 0) {
            return null;
        }
        try {
            return objectMapper.readValue(json, clazz);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 把Object转化成json格式的字符串
     *
     * @param obj
     * @return
     */
    public static String toString(Object obj) {
        if (obj == null) {
            return "{}";
        }
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.error(e.getMessage());
            return "{}";
        }
    }

    /**
     * 把一个JSON对象数组描述字符转化为List
     *
     * @param json
     * @return
     */
    @SuppressWarnings("unchecked")
    public static List<Map> parseToMapList(String json) {
        return (List<Map>) parseToObjList(json, Map.class);
    }

    /**
     * 把一个JSON对象数组描述字符转化为List
     *
     * @param json
     * @param clazz
     * @return
     */
    public static List<?> parseToObjList(String json, Class<?> clazz) {
        return parse(json, List.class);
    }


    /**
     * 按名称过滤属性
     */
    @SuppressWarnings("deprecation")
    @JsonFilter("JacksonFilter")
    public static class NamedPropertyFilter extends FilterProvider {
        private String[] names;
        private boolean exclude;

        public void addFilter(String[] names, boolean exclude) {
            this.names = names;
            this.exclude = exclude;
        }

        @Deprecated
        @Override
        public BeanPropertyFilter findFilter(Object filterId) {
            throw new UnsupportedOperationException("Access to deprecated filters not supported");
        }

    }

}
